#ifndef CSOLAR_NEBULA_H
#define CSOLAR_NEBULA_H

#include <string>
#include <iostream>
#include <fstream>
using namespace std;

#include "../Particle/CParticle.h"

template <typename _PO>
class CSolarNebula {
public:
	typedef _PO		particle_t;
	typedef typename particle_t::value_pattern_t	value_pattern_t;
	typedef typename particle_t::value_point_t		value_point_t;
	typedef typename particle_t::label_t			label_t;
	typedef typename particle_t::gravity_t			gravity_t;
	typedef typename particle_t::velocity_t			velocity_t;
	typedef typename particle_t::container_t		container_t;
	typedef typename particle_t::pattern_t			pattern_t;

public:
	particle_t	*** _nebula;
	int				_size;

	CSolarNebula (string _filename, int _features, int _total, int _v, bool _l =  false){		
		int _m = (int)ceil(sqrt((double)_total));
		_size = _total;
		ifstream _file (_filename.c_str());

		_nebula = new particle_t ** [_m];
		for (int i = 0; i < _m; i++){
			_nebula[i] = new particle_t * [_m];
			for (int k = 0; k < _m; k++){
				if (!_file.eof()) {
					particle_t *_particle = new particle_t (_v); 
					(*_particle)[X] = i;
					(*_particle)[Y] = k;

					value_pattern_t _feature = NULL;
					for (int _i = 0; _i  < _features;  _i++){
						_file >> _feature; (*_particle) << _feature;
					}
					_particle->lock_pattern();
					
					if (_l) {
						label_t	_label = "";
						_file >> _label; (*_particle) << _label;
					}
					_nebula[i][k] = _particle;
				} else _nebula[i][k] = NULL;
			}
		}
		_file.close();
	}

	template <typename __PO>
	friend ostream& operator << (ostream& out, const CSolarNebula<__PO>& _s){
		int _m = (int)ceil(sqrt((double)_s._size));
		for (int i = 0; i < _m; i++){
			out << i << "\t";
			for (int k = 0; k < _m; k++){
				if (_s._nebula[i][k])
					out << (_s._nebula[i][k]->_pattern)() << " ";
				else out << ". ";
			}
			out << endl;
		}
		out << endl;
		return out;
	}

	~CSolarNebula(){
	}

};


#endif 